/*
 * @file gkt_window_event.h
 */

#ifndef GKT_EVENT_H
#define GKT_EVENT_H

#include "gkt_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 
 * event major_type
 */
enum {
	GKT_EVENT_WINDOW = 0,
	GKT_EVENT_WIDGET,

	GKT_EVENT_SYSTEM,
	GKT_EVENT_TIMER,
	GKT_EVENT_VOICE,
	GKT_EVENT_USER,

	GKT_EVENT_MASKABLE,
	GKT_EVENT_KEY = GKT_EVENT_MASKABLE,
	GKT_EVENT_FPS,
	GKT_EVENT_CARD,
	GKT_EVENT_BLE,
#if defined(GKT_CONFIG_FACE_ID_ENABLE) && GKT_CONFIG_FACE_ID_ENABLE
	GKT_EVENT_FACE_ID,
#endif
	GKT_EVENT_MAX
};

#define GKT_EVENT_MASKABLE_BITS	\
	(((1U << (GKT_EVENT_MAX - GKT_EVENT_MASKABLE)) - 1) << GKT_EVENT_MASKABLE)

enum {
	GKT_EVENT_HANDLE_COMPLETE = 0,
	GKT_EVENT_HANDLE_STAGE,
	GKT_EVENT_HANDLE_CONTINUE,
	GKT_EVENT_HANDLE_MAX
};

#define GKT_EVENT_F_STAGED	(1U << 0)
#define GKT_EVENT_F_BYPASS	(1U << 15)

#define GKT_EVENT_DATA_WORDS	2
typedef struct _gkt_event {
	int16_t	window_id;	/* window_id */
	uint16_t	flags;
	uint16_t	major_type;	/* GKT_EVENT_WINDOW/TIMER/... */
	uint16_t	minor_type;	
	uint32_t	data[GKT_EVENT_DATA_WORDS];
} gkt_event_s;

typedef int (*gkt_event_init_fn)(void);
typedef void (*gkt_event_mask_fn)(int masked, uint32_t flags);
typedef int (*gkt_event_handler)(gkt_event_s *event);
typedef struct _gkt_event_desc {
	uint32_t	major_type;
	gkt_event_init_fn	init;
	gkt_event_mask_fn	mask;
	gkt_event_handler	handler;
} gkt_event_desc_s;

#define GKT_EVENT_DESC_DEFINE(NAME, name)	\
	static const gkt_event_desc_s __sc_event_##name##_desc \
		__SECTION(.rodata.event.desc) __USED = \
	{	\
		.major_type	= GKT_EVENT_##NAME,	\
		.init = gkt_##name##_init,	\
		.mask = gkt_##name##_mask,	\
		.handler	= gkt_##name##_event_handler,	\
	}

int gkt_event_put(const gkt_event_s *event, uint32_t timeout);
int gkt_event_get(gkt_event_s *event, uint32_t timeout);
void gkt_event_stage(const gkt_event_s *event);

void gkt_event_mask(uint32_t mask_bits);
void gkt_event_unmask(uint32_t unmask_bits);

void gkt_event_mask_single(uint32_t major_type, uint32_t flags);
void gkt_event_unmask_single(uint32_t major_type);
void gkt_event_unmask_single_flags(uint32_t major_type, uint32_t flags);

int gkt_event_is_masked(uint32_t major_type);

gkt_event_handler gkt_event_get_handler(uint32_t major_type);

int gkt_event_init(void);

#ifdef __cplusplus
}
#endif

#endif	/* GKT_EVENT_H */

